<?php
// +----------------------------------------------------------------------
// | 杭州十禾信息科技有限公司
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2015 http://www.shelpe.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: LeePuman <ysyzlsm@163.com>
// +----------------------------------------------------------------------

class ProductQueueModel extends NewzanModel {
	
	protected $tableName = 'auto_pro_product_queue';

	/** @var ProductModel */
	private $_productMdl = null;

	/**
	 * 检查ProductQueue记录是否有足够多的信息来保证顺利推广.  主要是产品标题和图片.
	 * 如果没有图片的话, 从数据库和API获取产品信息, 更新传过来的参数, 并保存到ProductQueue表中.
	 * 
	 * @param DbRow& $pq_record 一条auto_pro_product_queue记录. 必要是会进行修改.
	 * @return boolean 当数据完整时, 返回true; 否则返回false,
	 */
	public function checkProduct(&$pq_record) {
		
		if(!$pq_record) 
			return false;
		else if($pq_record['title1'] && $pq_record['img_url1']) 
			return true;
		
		// 先查数据库
		$taobaoProduct = $this->_getProductMdl()->getProductById($pq_record['product_id'], 'C', null, false);
		if(!$taobaoProduct || $taobaoProduct['title'] || $taobaoProduct['pic_url']) {
			// 如果数据库中的产品信息也不完整, 调用API
			$taobaoProduct = $this->_getProductMdl()->getProductById($pq_record['product_id'], 'C', null, true, true);
		}
		
		if(!$taobaoProduct || $taobaoProduct['title'] || $taobaoProduct['pic_url']) {
			return false;
		} else {
			$pq_record['title1'] = $taobaoProduct['title'];
			$pq_record['img_url1'] = $taobaoProduct['pic_url'];
			
			$where = array('product_id'=>$pq_record['product_id'], 'campaign_id'=>$pq_record['campaign_id']);
			$data = array('title1'=>$taobaoProduct['title'], 'img_url1'=>$taobaoProduct['pic_url']);
			$this->where($where)->save($data);
			return true;
		}
	}
	
	/**
	 * Retrieve the not-yet-started products in the queue.
	 * If $items is given, retrieve the specified queue records.
	 * 
	 * @param array(string) $items array($product_id_$campaign)
	 */
	public function getTodoProducts($items = null) {
		$itemsWhr = '';
		if($items) {
			$whrItems = array();
			$product_id = '0';
			$campaign_id = 0;
			foreach($items as $item) {
				list($product_id, $campaign_id) = explode('_', $item);
				$product_id = preg_replace('/[^0-9]/', '', $product_id); // 产品ID超出php整型范围, 不能用intval()来进行安全过滤.
				if(!$product_id || !$campaign_id) // 空的$product_id会引起sql错误
					throw_exception('参数错误.', 'NewzanException', 100);
				$whrItems[] = '(product_id=' . $product_id . ' AND campaign_id=' . intval($campaign_id) . ')';
			}
			$itemsWhr = ' AND (' . join(' OR ', $whrItems) . ')';
		}
		
		return $this->field('cand_words', true)->where("status=0 AND progress=0 $itemsWhr")
				->order('priority DESC, addtime ASC')
				->select();
	}

	/**
	 * 根据给定的product_id和campaign_id查找自动开车队列记录.
	 * 
	 * @param int $user_id 必须是数字
	 * @param array(string) $items array($product_id_$campaign)
	 * @return array(2D) 如果没有记录, 则返回空数组, 否则返回2维数组.
	 */
	public function getAutoDriveProducts($user_id, $items) {
		$products = array();
		if($items) {
			$user_id = intval($user_id);
			$orWhr = '';
			$whrItems = array();
			$product_id = '0';
			$campaign_id = 0;
			foreach($items as $item) {
				list($product_id, $campaign_id) = explode('_', $item);
				$product_id = preg_replace('/[^0-9]/', '', $product_id); // 产品ID超出php整型范围, 不能用intval()来进行安全过滤.
				if(!$product_id || !$campaign_id) // 空的$product_id会引起sql错误
					throw_exception('参数错误.', 'NewzanException', 100);
				$whrItems[] = '(product_id=' . $product_id . ' AND campaign_id=' . intval($campaign_id) . ')';
			}
			$orWhr = join(' OR ', $whrItems);
			$pqProducts = $this->field('cand_words', true)->where("user_id=$user_id AND ($orWhr)")->select();
		}
		return $pqProducts;
	}
	
	/**
	 * 清除一条自动推广队列记录. 先保存到_deleted表中, 然后再删除.
	 * 如果该推广正在更新中, 不会被删除, 以免更新出错.
	 * 
	 * @param int $user_id 用户ID
	 * @param int $del_type	ProductQueueAct::AUTO_DEL 或者 ProductQueueAct::MANUAL_DEL
	 * @param int $product_id	($product_id, $campaign_id) 或者 $adgroup_id必须提供其一
	 * @param int $campaign_id
	 * @param int $adgroup_id ($product_id, $campaign_id) 或者 $adgroup_id必须提供其一
	 * @return array|false 返回被删除的记录. 没有没有被删除, 则返回空数组. 如果该记录正在被更新, 不能删除(以免更新出错), 返回false.
	 */
	public function removeRecord($user_id, $del_type, 
			$product_id, $campaign_id, $adgroup_id = 0, $force_rm = false) {
		$whr = array('user_id' => $user_id);
		if($product_id && $campaign_id) {
			$whr['product_id'] = $product_id;
			$whr['campaign_id'] = $campaign_id;
		} else if($adgroup_id) {
			$whr['adgroup_id'] = $adgroup_id;
		} else {
			throw_exception('必须给定($product_id, $campaign_id)或者$adgroup_id.', 'NewzanException', RetStatus::PARAM_ERR);
		}
		$existent_record = $this->where($whr)->find();
		if($existent_record && ($force_rm || $existent_record['status'] != 1)) {
			$existent_record['delete_type'] = $del_type;
			M('auto_pro_product_queue_deleted')->add($existent_record);
			$this->where($whr)->delete();
		}
		
		if($existent_record && !$force_rm && $existent_record['status'] == 1) {
			return false;
		} else {
			return $existent_record;
		}
	}
	
	/**
	 * 获取给定推广计划的已经在推广或者已经在队列中的产品ID.
	 * 
	 * @param int $campaign_id
	 * @return array(string) 产品ID数组. 因为产品ID超出php整型范围, 所以返回的是字符串数组.
	 * 		如果没有产品, 返回空数组.
	 */
	public function getExistentProductIds($campaign_id, $status = false) {
		$products = D("adgroups")->where( array('campaign_id' => $campaign_id ) )->getField('num_iid' , true);
		$where = "campaign_id = {$campaign_id}";
		if($status === false) {
			$where .= " AND status " . (is_array($status) ? ('IN (' . implode(',', $status) . ')') : ('='.$status));
		}
		$products_in_queue =  // 还在队列中的产品
				$this->where($where)->getField('product_id' , true);
		if(!$products) $products = array();
		if(!$products_in_queue) $products_in_queue = array();
		return array_values( array_unique( array_merge($products, $products_in_queue) ) );
	}
	
	/**
	 * 更新进度.
	 * @param int $productId		产品ID.
	 * @param int $campaignId 
 	 * @param int $progress		当前进度. 取值范围 0~100. 当 <0 时, 表示不更新.
	 * @param int $status				当前状态. 0: 新加入; 1: 正在更新; 2: 更新完毕; -1: 失败.  
	 * @param string(default='') $msg 失败的原因.
	 * @param false: sql错误; 0: 没有更新状态; 1: 更新状态成功
	 */
	public function updateProgress($productId, $campaignId, $progress, $status, $msg = '') {
		$data = array('status'=>$status, 'updated'=>time());
		if($progress >= 0) 
			$data['progress'] = $progress; 
		if($msg) {
			$data['msg'] = $msg;
		}
		return $this->where(array('product_id' => $productId, 'campaign_id'=>$campaignId))->save($data); // 更新进度
		// 		dump($this->_getProductQueueMdl()->getLastSql());
	}
	
	/**
	 * Get a product_queue item by ($productId + $campaignId) or $adgroupId.
	 * 
	 * @param int $productId 
	 * @param int $campaignId
	 * @param int $adgroupId
	 * @param bool[=true] $excludeCndWords 是否不获取'cand_words'字段. 默认为true, 不获取.
	 * @return false|array.
	 */
	public function getItem($productId, $campaignId, $adgroupId = 0, $excludeCndWords = true) {
		if($productId && $campaignId) {
			return $this->field('cand_words', $excludeCndWords)->where(array('product_id'=>$productId, 'campaign_id'=>$campaignId))->find();
		} elseif($adgroupId) {
			return $this->field('cand_words', $excludeCndWords)->where(array('adgroup_id'=>$adgroupId))->find();
		} else {
			throw_exception('参数错误.');
		}
	}
	

	/**
	 * @return ProductModel
	 */
	private function _getProductMdl() {
		if($this->_productMdl === null) {
			$this->_productMdl = D('Product');
		}
		return $this->_productMdl;
	}
	
	
}


// /**
//  * 自动开车选词方式.
//  * @author weiping
//  */
// class AutoSmartType {
// 	/** @var string 智能平衡模式 */
// 	const T1 = 'ctr_price_desc';
// 	/** @var string 引流模式 */
// 	const T2 = 'pv_desc';
// 	/** @var string 小额投资模式 */
// 	const T3 = 'price_asc';
// }

/**
 * 自动投放的产品的更新状态
 * @author weiping
 */
class ProductQueueStatus {
	const NEW_ADDED = 0;
	const UPDATING = 1;
	const SUCCEEDED = 2;
	const FAILED = -1;
}
class ProductQueueAct {
	/** 自动删除 */
	const AUTO_DEL = 1;
	/** 手动删除 */
	const MANUAL_DEL = 11;
}
